const fs = require('fs');
const urlUtil = require("url");
const shell = require('shelljs');
const chalk = require('chalk');
const cliProgress = require('cli-progress');
const chrome = require('selenium-webdriver/chrome');
const firefox = require('selenium-webdriver/firefox');
const {Builder, By, Key, until} = require('selenium-webdriver');

const yargs = require('yargs/yargs')
const { hideBin } = require('yargs/helpers')
const argv = yargs(hideBin(process.argv)).argv

const screen = {
  width: 640,
  height: 480
};
const pageContentSelectors = [
  'h1',
  'h2',
  'h3',
  'h4',
  'h5',
  'h6',
  'p',
  '[fui-docs-example-title]',
  '[fui-docs-api]',
];
const pageContents = [];

async function generateSearchContextFromUrl(driver, url) {
  try {
    // Navigate to Url
    await driver.get(url);

    // Wait for navigation menu to be ready
    await driver.wait(until.elementLocated(By.css('ul.nav')), 10);

    // Walk through all nav menu item
    const navItems = await driver.findElements(By.css('ul.nav li'));

    // Create a new progress bar instance
    const progressBar = new cliProgress.SingleBar({
      format: 'progress [{bar}] {percentage}% | ETA: {eta}s | {value}/{total} | {duration_formatted}'
    }, cliProgress.Presets.legacy);
    progressBar.start(navItems.length, 0);

    for (let index = 0; index < navItems.length; index++) {
      const navItem = navItems[index];
      const navTitle = (await navItem.getText()).trim();
      navItem.click();
      // Wait for docs content to load
      await driver.wait(until.elementLocated(By.css('.docs-container')), 10);
      const currentUrl = await driver.getCurrentUrl();
      const pageContentElement = await driver.findElement(By.css('.docs-container'));
      const pageContentNodes = await pageContentElement.findElements(By.css(pageContentSelectors.join(', ')));

      let contextContent = null;
      for (let index = 0; index < pageContentNodes.length; index ++) {
        const pageContentNode = pageContentNodes[index];
        const nodeText = await pageContentNode.getAttribute('innerText');
        const nodeId = await pageContentNode.getAttribute('id');
        if (nodeText) {
          const content = {
            title: navTitle,
            url: urlUtil.parse(currentUrl).pathname,
            text: nodeText,
            id: nodeId,
          };

          if (nodeId) {
            contextContent = content;
          } else { // If the content has no id, assign last content with id to its context
            content.context = contextContent;
          }

          pageContents.push(content);
        }
      }

      progressBar.update(index + 1);
    }
    progressBar.stop();
  } catch(error) {
    console.error(error);
  }
};

(async function generateSearchContext() {
  const pageUrl = argv.url || 'http://localhost:4302';
  const destPath = argv.dest || 'doc/assets/search/';
  const browser = argv.browser || 'chrome';
  const driver = await new Builder()
    .forBrowser(browser)
    .setChromeOptions(new chrome.Options().headless().windowSize(screen))
    .setFirefoxOptions(new firefox.Options().headless().windowSize(screen))
    .build();
  const entries = [
    '/gallery',
    '/guides',
  ];

  for (let entry of entries) {
    entryUrl = pageUrl + entry;
    shell.echo(chalk.green(`Generating search context from ${entryUrl}.`));
    await generateSearchContextFromUrl(driver, entryUrl);
  }
  driver.quit();

  shell.echo(chalk.green(`Writing search context to '${destPath}'.`));
  shell.mkdir(`-p`, `${destPath}`);
  fs.writeFileSync(`${destPath}search-context.json`, JSON.stringify(pageContents, null, 2));
  shell.echo(chalk.green(`Finish generating search context.`));
})();

